package cn.player.download.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;

import cn.player.utils.Constant;
import cntv.player.core.util.LogUtil;

public class WebServer extends Thread {
	
	public static final String SUFFIX_ZIP = "..zip";
	public static final String SUFFIX_DEL = "..del";
	
	
	private static final String WEBROOT = "/";
	private boolean isLoop = false;

	public WebServer() {
		super();
	}
	
	
	/**
	 * 检查端口port是否被占用了
	 * 
	 * @param port
	 * @return true 被占用了， false 没被占用
	 */
	public static boolean checkPort(int port) {
		InetSocketAddress address = null;
		Socket socket = null; 
		try {
			socket = new Socket();
			address = new InetSocketAddress("127.0.0.1", port);
			socket.bind(address);
			LogUtil.e("zl", "检查端口号是否被占用 false address = " + address);
			return false;
		} catch (Exception e) {
			LogUtil.e("zl", "检查端口号是否被占用 true address = " + address + ",e = " + e.getMessage());
			return true;
		}finally{
			try {
				address = null;
				if(socket != null){
					socket.close();
					socket = null;
				}
			} catch (Exception ex) {
				// TODO: handle exception
				ex.printStackTrace();
			}
		}
	}
	
	private int getAvailablePort() {
		for (int i = Constant.PORT_START; i < Constant.PORT_END; i++) {
			if (!checkPort(i)) {
				Constant.PORT = i;
				return Constant.PORT;
			}
		}
		return Constant.PORT;
	}
	
	@Override
	public void run() {
		ServerSocket serverSocket = null;
		try {
			// 创建服务器套接字
//			serverSocket = new ServerSocket(Constant.PORT);
			serverSocket = new ServerSocket(getAvailablePort());
			// 创建HTTP协议处理器
			BasicHttpProcessor httpproc = new BasicHttpProcessor();
			// 增加HTTP协议拦截器
			httpproc.addInterceptor(new ResponseDate());
			httpproc.addInterceptor(new ResponseServer());
			httpproc.addInterceptor(new ResponseContent());
			httpproc.addInterceptor(new ResponseConnControl());
			// 创建HTTP服务
			HttpService httpService = new HttpService(httpproc,
					new DefaultConnectionReuseStrategy(),
					new DefaultHttpResponseFactory());
			// 创建HTTP参数
			HttpParams params = new BasicHttpParams();
			params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
					.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE,8 * 1024)
					.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
					.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
					.setParameter(CoreProtocolPNames.ORIGIN_SERVER,"WebServer/1.1");
			// 设置HTTP参数
			httpService.setParams(params);
			// 创建HTTP请求执行器注册表
			HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
			// 增加HTTP请求执行器
			reqistry.register("*" + SUFFIX_ZIP, new HttpZipHandler(WEBROOT));
			reqistry.register("*" + SUFFIX_DEL, new HttpDelHandler(WEBROOT));
			reqistry.register("*", new HttpFileHandler(WEBROOT));
			// 设置HTTP请求执行器
			httpService.setHandlerResolver(reqistry);
			/* 循环接收各客户端 */
			isLoop = true;
			while (isLoop && !Thread.interrupted()) {
				// 接收客户端套接字
				Socket socket = serverSocket.accept();
				// 绑定至服务器端HTTP连接
				DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
				conn.bind(socket, params);
				// 派送至WorkerThread处理请求
				Thread t = new WorkerThread(httpService, conn);
				t.setDaemon(true); // 设为守护线程
				t.start();
			}
		} catch (IOException e) {
			isLoop = false;
			LogUtil.e("zl", "IOException ,e = " + e.getMessage());
			e.printStackTrace();
		} finally {
			try {
				if (serverSocket != null) {
					serverSocket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void close() {
		isLoop = false;
	}

}
